﻿<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<!--
This sample illustrates using templates for a more complete and 
realistic scenario. 

It uses the NetFlix OData JSONP services as a source of data. 

This version of the movies sample demo uses the 
	$( templateSelector ).tmpl( data ).appendTo( targetSelector ) 
pattern, and does not use the tmplCmd plugin or the rendered event.
-->
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<title>jQuery + OData + Netflix Catalog API</title>
    <link href="../css/jquery-ui-1.8.1.custom.css" rel="stylesheet" type="text/css" />
    <link href="../css/movies.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="about">
	This is a demo of updates to the jQuery templating feature, proposed by Microsoft.<br/>
	The source can be viewed here: <a href="http://github.com/nje/jquery-tmpl/">NJE Templating Branch on GitHub</a>
</div>	
<div id="pageBody">
<h1>Netflix: Book a Movie...</h1>

	<ul id="genres">
		<li class="selected">Cartoons</li>
		<li>Drama</li>
		<li>Foreign</li>
		<li>Action Classics</li>
		<li>Horror</li>
		<li>Sci-Fi Cult Classics</li>
	</ul>
	
	<div id="pager"><ul class="pages"><li class="pgEmpty">first</li><li class="pgEmpty">prev</li></ul></div>
	
	<div id="movieList"></div>
	<table id="bookingsList">
		<tbody><tr class="cart"><td class="cart-false" colspan="4">
			<span class="text">0 items in Cart...</span> 
		</td></tr></tbody>
	</table>
	<br/>
</div>
<script src="http://code.jquery.com/jquery.js"></script>
<script src="../../../jquery.tmpl.js" type="text/javascript"></script>
<script src="../components/jquery.pager.js" type="text/javascript"></script>
<script src="../components/jquery-ui-1.8.1.custom.js" type="text/javascript"></script>

<script id="movieTmpl" type="text/html">
	<div>
		<div><img src="${BoxArt.LargeUrl}" /> </div>
		<strong>${Name}</strong>
		<p>{{html Synopsis}}</p>
		<input type="button" title="Buy tickets for '${Name}'" value="Add to cart..." class="buyButton"/>
		<br/>
	</div>
</script>

<script id="cartTmpl" type="text/html">
	<td class="cart-${!!count}" colspan="4">
		<span class="text">${count} items in Cart...</span> 
		{{if count}} 
			<span id="submit">Checkout</span> 
			<span id="cancel">Remove All</span>
			{{if count>1}} 
				<span id="sort"><span id="sortBtn">Sort</span>:
					<select>
						<option value="0" {{if sortBy==="0"}}selected{{/if}}>Name A-Z</option>
						<option value="1" {{if sortBy==="1"}}selected{{/if}}>Name Z-A</option>
						<option value="2" {{if sortBy==="2"}}selected{{/if}}>Date</option>
					</select>
				</span>
			{{/if}}
			</select>
		{{/if}}
	</td>   
</script>

<script id="bookingTitleTmpl" type="text/html">
	<tr class="bookingTitle${$item.mode}">
		<td>${movie.Name}</td><td>${movieTheater}</td>
		<td>${formatDate(date)}</td>
		<td>
			${quantity}
			<span class="ui-icon close"></span>
		</td>
	</tr>
</script>

<script id="bookingEditTmpl" type="text/html">
	{{tmpl(this.data, {mode: "Edit"}) "#bookingTitleTmpl"}}
	<tr class="bookingEdit">
		<td colspan="4">
			<div class="fields">
				<span>Movie Theater: </span><input class="theater" type="text" value="${movieTheater}" /><br/>
				<span>Date: </span><input class="date" type="text" value="${formatDate(date)}" /><br/>
				<span>Quantity: </span><input class="quantity" type="text" value="${quantity}" />
			</div>
			<div><img src="${movie.BoxArt.LargeUrl}" /></div>
		</td>
	</tr>
</script>

<script type="text/javascript">
	var genre="Cartoons", pageIndex=1, pageSize=3, pageCount=0,
		cart = { bookings: {}, count: 0, sortBy:0 }, bookingTmplItems = {}, selectedBooking;
		
	getMovies( pageIndex );

	$( "#genres li" ).click( selectGenre );

	$( ".cart" )
		.delegate( "select", "change", sort )
		.delegate( "#sortBtn", "click", sort )
		.delegate( "#submit", "click", function() {
			alert( cart.count + " bookings submitted for payment...");
			removeBookings(); 
		})
		.delegate( "#cancel", "click", function() {
			removeBookings(); 
		})
		.empty();

	$( "#cartTmpl" )
		.tmpl( cart )
		.appendTo( ".cart", cart );

	var cartTmplItem = $( ".cart td" ).tmplItem();

	function selectGenre() {
		$( "#genres li" ).removeClass( "selected" );
		$( this ).addClass( "selected" );

		pageIndex = 1;
		genre = encodeURI( $(this).text() ); 
		getMovies( pageIndex );
	}

	function sort() {
		var compare = compareName, reverse = false, data = [];
		cart.sortBy = $( "#sort select" ).val();
		switch ( $( "#sort select" ).val() ) {
			case "1":
				reverse = true;
				break;
			case "2":
				compare = compareDate;
				break;
		} 

		for ( var item in cart.bookings ) {
			data.push( cart.bookings[item] ); 
		}
		data = data.sort( compare );

		for ( var i = 0, l = data.length; i < l; i++ ) {
			$( bookingTmplItems[data[i].movie.Id].nodes ).appendTo( "#bookingsList" );
		}
	
		function compareName( a, b ) {
			return a == b ? 0 : (((a.movie.Name > b.movie.Name) !== reverse) ? 1 : -1);
		}
		function compareDate( a, b ) {
			return a.date - b.date;
		}
	}
		
	function getMovies( index ) {
		var query = "http://odata.netflix.com/Catalog/Genres('" + genre + "')/Titles" +
			"?$format=json" +
			"&$inlinecount=allpages" +				// get total number of records
			"&$skip=" + (index-1) * pageSize +		// skip to first record of page
			"&$top=" + pageSize;					// page size

		pageIndex = index;

		$( "#movieList" )
			.fadeOut( "medium", function () {
				$.ajax({
					dataType: "jsonp",
					url: query,
					jsonp: "$callback",
					success: showMovies
				});
			});
	}
	
	function showMovies( data ) {
		pageCount = Math.ceil( data.d.__count/pageSize ),
			movies = data.d.results;
		
		$( "#pager" ).pager({ pagenumber: pageIndex, pagecount: pageCount, buttonClickCallback: getMovies });
		
		// show movies in template
		$( "#movieList" ).empty();
		
		$( "#movieTmpl" )
			.tmpl( movies ) //, { rendered: onMovieRendered } )
			.appendTo( "#movieList" )
			.find( "div" ).fadeIn( 4000 ).end()
			.find( ".buyButton" ).click( function() { 
				buyTickets( $(this).tmplItem().data ); 
			});
		
		$( "#movieList" ).fadeIn( "medium" )
	}

	function buyTickets( movie ) {
		// Add item to cart
		var booking = cart.bookings[movie.Id];
		if ( booking ) {
			booking.quantity++;
		} else {
			cart.count++;
			updateItem( cartTmplItem );
			booking = { movie: movie, date: new Date(), quantity: 1, movieTheater: "" };
		}
		selectBooking( booking );
	}

	function selectBooking( booking ) {
		if ( selectedBooking ) {
			if ( selectedBooking === booking ) {
				updateBooking( bookingTmplItems[selectedBooking.movie.Id]);
				return;
			}
			// Collapse previously selected booking, and switch to non-edit view
			var oldSelected = selectedBooking; 
			$( "div", bookingTmplItems[oldSelected.movie.Id].nodes ).animate( { height: 0 }, 500, function() { 
				switchView( oldSelected );
			});
		}
		selectedBooking = booking;
		if ( !booking ) {
			return;
		}
		if ( cart.bookings[booking.movie.Id] ) {
			switchView( booking, true );
		} else {
			cart.bookings[booking.movie.Id] = booking;
			var bookingNode = $( "#bookingEditTmpl" )
				.tmpl( booking, { animate: true } ) 
				.appendTo( "#bookingsList" ).last()[0];
				
			// Attach handlers etc. on the rendered template.
			// Pass the template context of the second tr, which the context for the "bookingEditTmpl" template
			var newItem = $.tmplItem( bookingNode );
			bookingTmplItems[booking.movie.Id] = newItem;
			bookingEditRendered( newItem ); 
		}
	}

	function bookingEditRendered( item ) {
		var data = item.data, nodes = item.nodes;
		
		$( nodes[0] ).click( function() { 
			selectBooking();
		});

		$( ".close", nodes ).click( removeBooking );
		
		$( ".date", nodes ).change( function() {
			data.date = $(this).datepicker( "getDate" );
			updateBooking( item );
		})
		.datepicker({ dateFormat: "DD, d MM, yy" });

		$( ".quantity", nodes ).change( function() {
			data.quantity = $(this).val();
			updateBooking( item );
		});

		$( ".theater", nodes ).change( function() {
			data.movieTheater = $(this).val();
			updateBooking( item );
		});

		if ( item.animate ) {
			$( "div", nodes ).css( "height", 0 ).animate( { height: 116 }, 500 );
		}
	}
	
	function bookingRendered( item ) {
		$( item.nodes ).click( function() { 
			selectBooking( item.data );
		});
		$( ".close", item.nodes ).click( removeBooking );
	}

	function switchView( booking, edit ) {
		if ( !booking ) {
			return;
		}
		var item = bookingTmplItems[booking.movie.Id],
			tmpl = $( edit ? "#bookingEditTmpl" : "#bookingTitleTmpl" ).templates(); 
		if ( item.tmpl !== tmpl) {
			item.tmpl = tmpl; 
			updateItem( item );
			(edit ? bookingEditRendered : bookingRendered)( item );
		}
	}

	function updateBooking( item ) {
		item.animate = false;
		updateItem( item );
		(item.data === selectedBooking ? bookingEditRendered : bookingRendered)( item );
		item.animate = true;
	}

	function removeBooking() {
		var booking = $.tmplItem(this).data;
		if ( booking === selectedBooking ) {
			selectedBooking = null;
		}
		delete cart.bookings[booking.movie.Id];
		cart.count--;
		updateItem( cartTmplItem );
		$( bookingTmplItems[booking.movie.Id].nodes ).remove();
		delete bookingTmplItems[booking.movie.Id];
		return false; 
	}
	
	function removeBookings() {
		for ( var item in bookingTmplItems ) {
			$( bookingTmplItems[item].nodes ).remove();
			delete bookingTmplItems[item];
		}
		bookingTmplItems = {};
		cart.count = 0;
		cart.bookings = {};
		selectedBooking = null;
		updateItem( cartTmplItem );
	}
	
	function formatDate( date ) {
		return date.toLocaleDateString();
	}

	function updateItem( item ) {
		var coll = item.nodes;
		$.tmpl( null, null, null, item ).insertBefore( coll[0] );
		$( coll ).remove();
	}

	function removeContext( item ) {
		$( item.nodes ).remove();
	}
</script>

</body>
</html>
